package com.upb.webserver.chainorg;

import cn.hutool.core.collection.CollectionUtil;
import com.upb.webserver.chain.ChainManager;
import com.upb.webserver.common.constant.Constant;
import com.upb.webserver.common.enums.OrgTypeEnum;
import com.upb.webserver.common.enums.PlatformEnum;
import com.upb.webserver.common.pojo.base.BasePageResponse;
import com.upb.webserver.common.pojo.chainorg.RspChainOrgVO;
import com.upb.webserver.common.tools.JsonUtils;
import com.upb.webserver.common.tools.MybatisExampleTools;
import com.upb.webserver.dao.entity.TbChain;
import com.upb.webserver.dao.entity.TbChainOrg;
import com.upb.webserver.dao.entity.TbChainOrgExample;
import com.upb.webserver.dao.entity.TbOrg;
import com.upb.webserver.dao.mapper.TbChainOrgMapper;
import com.upb.webserver.dao.mapper.TbOrgMapper;
import com.upb.webserver.org.OrgManager;
import com.upb.webserver.org.OrgService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Slf4j
@Service
public class ChainOrgService {
    @Autowired
    private TbChainOrgMapper chainOrgMapper;
    @Autowired
    private ChainManager chainManager;
    @Autowired
    private OrgManager orgManager;
    @Autowired
    private OrgService orgService;
    @Autowired
    private TbOrgMapper orgMapper;


    /**
     * @param chainId
     * @param orgId
     */
    @Transactional
    public void saveChainOrg(Integer chainId, Integer orgId, OrgTypeEnum orgTypeEnum) {
        log.info("start exec method [saveChainOrg]. chainId:{} orgId:{} orgTypeEnum:{}", chainId, orgId, orgTypeEnum);

        //check chainId
        TbChain tbChain = chainManager.verifyChainId(chainId);
        //check org
        orgManager.verifyOrgId(orgId);

        if (CollectionUtil.isNotEmpty(chainOrgMapper.selectByChainAndOrg(chainId, orgId))) {
            log.info("found record by chainId:{} and orgId:{}", chainId, orgId);
            return;
        }

        //save chain-org
        TbChainOrg tbChainOrg = new TbChainOrg();
        tbChainOrg.setOrgId(orgId);
        tbChainOrg.setChainId(chainId);
        tbChainOrg.setChainType(tbChain.getChainType());
        tbChainOrg.setOrgType(orgTypeEnum.getValue());
        tbChainOrg.setGmtCreate(new Date());
        tbChainOrg.setGmtModified(new Date());

        chainOrgMapper.insert(tbChainOrg);
        log.info("success exec method [saveChainOrg]. chainId:{} orgId:{}", orgId);
    }


    /**
     * @param pageNumber
     * @param pageSize
     * @param chainId
     * @return
     */
    public BasePageResponse queryChainOrgByPage(int pageNumber, int pageSize, Byte orgType, int chainId) {
        log.info("start exec method [queryChainOrgByPage]. currentDeveloper:{} pageNumber:{} pageSize:{} orgType:{} chainId:{}", pageNumber, pageSize, orgType, chainId);
        BasePageResponse pageResponse = BasePageResponse.initialize();
        TbChainOrgExample example = MybatisExampleTools.initSamplePageExample(TbChainOrgExample.class, pageNumber, pageSize, new TbChainOrg(orgType, chainId));
        pageResponse.setTotalCount(chainOrgMapper.countByExample(example));
        if (pageResponse.getTotalCount() == 0) return pageResponse;

        List<RspChainOrgVO> rspList = new ArrayList<>();
        List<TbChainOrg> list = chainOrgMapper.selectByExample(example);

        list.stream().forEach(tbChainOrg -> {
            RspChainOrgVO chainOrgVo = new RspChainOrgVO();
            BeanUtils.copyProperties(tbChainOrg, chainOrgVo);

            TbOrg tbOrg = orgManager.verifyOrgId(tbChainOrg.getOrgId());
            chainOrgVo.setOrgName(tbOrg.getName());
            chainOrgVo.setOrgCompanyId(tbOrg.getCompanyId());
            rspList.add(chainOrgVo);
        });


        pageResponse.setData(rspList);

        log.info("success exec method [queryChainOrgByPage]. result:{}", JsonUtils.objToString(pageResponse));
        return pageResponse;
    }


    /**
     * @param creatorPlatform
     * @param creatorId
     * @param chainId
     * @return
     */
    public String getCreatorOrgName(Byte creatorPlatform, int creatorId, int chainId) {
        log.info("start exec method [getCreatorOrgName]. creatorPlatform:{} creatorId:{} chainId:{}", creatorPlatform, creatorId, chainId);
        if (PlatformEnum.DEV_OPS.getId() == creatorPlatform) {
            log.info("finish exec method [getCreatorOrgName] .result:{}", Constant.DEV_OPS_ADMIN_NAME_ZH);
            return Constant.DEV_OPS_ADMIN_NAME_ZH;
        }

        if (PlatformEnum.DEVELOPER.getId() != creatorPlatform) {
            log.warn("fail exec method [getCreatorOrgName].not support creatorPlatform:{}", creatorPlatform);
            return null;
        }

        //get orgIdList by creatorId
        Set<Integer> orgIdSetOfCreator = orgService.getOrgIdSetByDeveloperId(creatorId);

        //get orgIdList by chainId
        List<TbChainOrg> chainOrgList = chainOrgMapper.ListByChainId(chainId);
        if (CollectionUtil.isEmpty(orgIdSetOfCreator) || CollectionUtil.isEmpty(chainOrgList)) {
            log.warn("fail exec method [getCreatorOrgName].  orgIdSetOfCreator:{} chainOrgList:{}", JsonUtils.objToString(orgIdSetOfCreator), JsonUtils.objToString(chainOrgList));
            return null;
        }

        //case any org of creator
        Integer creatorOrgId = chainOrgList.stream()
                .filter(co -> orgIdSetOfCreator.contains(co.getOrgId()))
                .findFirst()
                .map(aof -> aof.getOrgId())
                .orElse(null);

        if (Objects.isNull(creatorOrgId)) {
            log.warn("fail exec method [getCreatorOrgName], not found org by  creatorId:{} and chainId:{}", creatorId, chainId);
            return null;
        }

        String orgName = orgMapper.selectNameByPrimaryKey(creatorOrgId);
        log.info("success exec method [getCreatorOrgName],  creatorId:{} and chainId:{}  result:{}", creatorId, chainId, orgName);
        return orgName;
    }

}
